package com.andnnl.queue;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 创建了一个泛型类 SimpleBlockingQueue，
 * 它具有 put 和 take 方法。put 方法用于向队列中添加元素，take 方法用于从队列中取出元素。
 * 这两个方法都使用了 ReentrantLock 和 Condition 来实现线程安全性和阻塞功能。
 *
 * put 方法的工作原理如下：
 *
 *      获取 putLock 锁。
 *      当队列已满时，调用 notFull.await() 方法，使当前线程等待在 notFull 条件上。
 *      当线程被唤醒时，将元素添加到队列中。
 *      调用 notEmpty.signalAll() 方法，唤醒等待在 notEmpty 条件上的线程。
 *      释放 putLock 锁。
 *
 * take 方法的工作原理与 put 方法类似，但它是基于 notEmpty 条件来实现阻塞功能的。
 * Created by chenss on 2024/4/3.
 */
public class SimpleBlockingQueue<T> {
    private final Queue<T> queue = new LinkedList<>();
    private final int capacity;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public SimpleBlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public void put(T item) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == capacity) {
                notFull.await();
            }
            queue.offer(item);
            notEmpty.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public T take() throws InterruptedException {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                notEmpty.await();
            }
            T item = queue.poll();
            notFull.signalAll();
            return item;
        } finally {
            lock.unlock();
        }
    }
}